#include "rs.h"

RS::RS(LBServer * lb ,unsigned int rsId,unsigned int bandwidth,unsigned int maxLoad,double spreadThreshold){
	_rsId = rsId;
	_bandwidth = bandwidth;
	_maxLoad = maxLoad;
	_spreadThreshold = spreadThreshold;
	_lb = lb;
	_currentLoad =0;
	pthread_mutex_init(&_rsMutex,NULL);
}
RS::~RS(){
	pthread_mutex_destroy(&_rsMutex);
}
int
RS::increaseCurrentLoad(){
	pthread_mutex_lock(&_rsMutex);
	_currentLoad ++;
	if( (double)_currentLoad > _spreadThreshold * _maxLoad){
		//cout<<" rs "<<_rsId<<" will spread,currentload = "<<_currentLoad<<",maxLoad = "<<_maxLoad<<",spread threshold = "<<_spreadThreshold<<endl;
		pthread_mutex_unlock(&_rsMutex);
		_lb->needSpread(_rsId,_fileList);
		//cout<<"rs "<<_rsId<<" spread the message ok!"<<endl;
	}else{
		pthread_mutex_unlock(&_rsMutex);
	}
	return 0;
}
void
RS::printRSInfo(){
	cout<<"for rs "<<_rsId<<": "<<_fileList.size()<<endl;
	for(unsigned int i = 0;i<_fileList.size();i++){
		cout<<_fileList[i]<<" ";
	}
	cout<<endl;
}

bool 
RS::haveFile(unsigned int fileId){
	vector<unsigned int >::iterator it;
	pthread_mutex_lock(&_rsMutex);
	for(it = _fileList.begin();it!=_fileList.end();it++){
		if((*it) == fileId){
			pthread_mutex_unlock(&_rsMutex);
			return true;
		}
	}
	pthread_mutex_unlock(&_rsMutex);
	return false;
}
int
RS::decreaseCurrentLoad(){
	pthread_mutex_lock(&_rsMutex);
	_currentLoad --;
	pthread_mutex_unlock(&_rsMutex);
	return 0;
}

int
RS::getCurrentLoad()  {
	unsigned int currentLoad;
	pthread_mutex_lock(&_rsMutex);
	currentLoad = _currentLoad ;
	pthread_mutex_unlock(&_rsMutex);
	return currentLoad;
}

unsigned int 
RS::canAffordClients(){
	unsigned int moreclients;
	pthread_mutex_lock(&_rsMutex);
	if(_maxLoad > _currentLoad){
		moreclients = _maxLoad -  _currentLoad;
	}else
		moreclients = 0;
	pthread_mutex_unlock(&_rsMutex);
	return moreclients;
}

int
RS::downloadFile(unsigned int clientId,unsigned int fileLen,unsigned int clientBandwidth){
	double speed;
	increaseCurrentLoad();
	unsigned int currentload = getCurrentLoad();
	double rsband = _bandwidth / (double)currentload;
	speed = (rsband >(double) clientBandwidth)?clientBandwidth:(double)rsband;
	unsigned int sendTime = (unsigned int) (fileLen * 8 * 1000000.0 / speed); 
	cout<<"********************client "<<clientId<<" will download "<<sendTime/1000000.0<<" secs from "<<_rsId<<endl;
	mysleep(sendTime);
	decreaseCurrentLoad();
	cout<<"********************client "<<clientId<<" download over"<<endl;
	return 0;
}

int
RS::addNewFile(unsigned int fileId){
	pthread_mutex_lock(&_rsMutex);
	_fileList.push_back(fileId);
	pthread_mutex_unlock(&_rsMutex);
	return 0;
}

int
RS::deleteFile(unsigned int fileId){
	vector<unsigned int> :: iterator it;
	pthread_mutex_lock(&_rsMutex);
	for(it = _fileList.begin();it!=_fileList.end();it++){
		if( *it  == fileId){
			_fileList.erase(it);
			break;
		}
	}
	pthread_mutex_unlock(&_rsMutex);
	return 0;
}


